#pragma once

#include "vc1prosdk.h"

namespace ManagedVC1
{
	namespace Exceptions
	{
        public ref class EmptyEncodingQueueException : public System::Exception
		{
		public:
			EmptyEncodingQueueException() : Exception("The encoding queue is empty") { }
		};

		public ref class InvalidFrameDataException : public System::Exception
		{
		public:
			InvalidFrameDataException() : Exception("The output buffer does not contain valid frame data") { }
		};

        public ref class HrException : public System::Exception
		{
		public:
            HrException(long hr) : Exception()
            {
                HResult = hr;
            }

            HrException(System::String^ message, long hr) : Exception(message)
            {
                HResult = hr;
            }
		};


		public ref class ExceptionUtility
		{
		public:
            static void ThrowExceptionForHr(long hr)
            {
                ThrowExceptionForHr(hr, System::String::Empty);
            }

            static void ThrowExceptionForHr(long hr, System::String^ comMethod)
            {
                if (FAILED(hr))
                {
                    System::Exception^ exp = GetExceptionForHr(hr);
                    exp->Data["COMMethod"] = comMethod;
                    throw exp;
                }
            }

			static System::Exception^ GetExceptionForHr(long hr)
			{
				switch (hr)
				{
				case ERR_ENCODER:
					return gcnew System::Exception("An unknown VC-1 encoder error occurred");
				case ERR_INVALIDARG:
					return gcnew System::ArgumentOutOfRangeException();
				case ERR_INVALIDSETTING:
					return gcnew System::ArgumentException("A setting is not valid for the current encoder state. This usually means the setting conflicts with an existing one");
				case ERR_MEMORY:
					return gcnew System::OutOfMemoryException();
				case ERR_POINTER:
					return gcnew System::NullReferenceException();
				case ERR_ENCODE_STARTED:
					return gcnew System::InvalidOperationException("The VC-1 encoder is already running");
				case ERR_IO:
                    return gcnew System::IO::IOException();
				case ERR_NOANALYZE_FRAME:
					return gcnew System::InvalidOperationException("You must specify at least one frame for analysis between calls to StartAnalyze and EndAnalyze");
				case ERR_NOTCONFIGURED:
					return gcnew System::InvalidOperationException("The encoder is not configured");
				case ERR_NOENCODE_FRAME:
					return gcnew System::InvalidOperationException("You must specify at least one frame for encoding between calls to StartEncode and EndEncode");
				case ERR_NOMORE_FRAMES:
					return gcnew EmptyEncodingQueueException();
				case ERR_NO_OP_FRAME:
					return gcnew InvalidFrameDataException();
				case ERR_NOSTART_ANALYZE:
					return gcnew System::InvalidOperationException("You must first call StartAnalyze");
				case ERR_NOSTART_ENCODE:
					return gcnew System::InvalidOperationException("You must first call StartEncode");
				default:
					return gcnew HrException(hr);
				}
			}
		};		
	}
}